﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CollectionExceptions.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Static factory class used to construct exceptions commonly thrown by collection and list implementations.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Collections
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// Static factory class used to construct exceptions commonly thrown by collection and list implementations.
    /// </summary>
    public static class CollectionExceptions
    {
        #region List Based Exceptions

        /// <summary>
        /// Creates an <see cref="ArgumentOutOfRangeException"/> that can be thrown when the <b>index</b>
        /// argument supplied to a list operation is out of bounds.
        /// </summary>
        /// <param name="argumentValue">The value of the index argument.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentOutOfRangeException IndexOutOfRange(object argumentValue)
        {
            return IndexOutOfRange(null, argumentValue);
        }

        /// <summary>
        /// Creates an <see cref="ArgumentOutOfRangeException"/> that can be thrown when the <b>index</b>
        /// argument supplied to a list operation is out of bounds.
        /// </summary>
        /// <param name="argumentName">The name of the index argument.</param>
        /// <param name="argumentValue">The value of the index argument.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentOutOfRangeException IndexOutOfRange(string argumentName, object argumentValue)
        {
            if (string.IsNullOrEmpty(argumentName))
            {
                argumentName = "index";
            }

            return new ArgumentOutOfRangeException(argumentName, ExceptionMessages.ListInsertIndexOutOfRange);
        }

        /// <summary>
        /// Creates an <see cref="ArgumentOutOfRangeException"/> that can be thrown when the <b>index</b>
        /// argument supplied to a list insert operation is out of bounds.
        /// </summary>
        /// <param name="indexArgumentValue">The value of the index argument.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentOutOfRangeException ListInsertIndexOutOfRange(object indexArgumentValue)
        {
            return ListInsertIndexOutOfRange(indexArgumentValue, null);
        }

        /// <summary>
        /// Creates and <see cref="ArgumentOutOfRangeException"/> that can be thrown when the <b>index</b>
        /// argument supplied to a list insert operation is out of bounds.
        /// </summary>
        /// <param name="indexArgumentValue">The value of the index argument.</param>
        /// <param name="indexArgumentName">The name of the index argument.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentOutOfRangeException ListInsertIndexOutOfRange(object indexArgumentValue, string indexArgumentName)
        {
            if (string.IsNullOrEmpty(indexArgumentName))
            {
                indexArgumentName = "index";
            }

            return new ArgumentOutOfRangeException(indexArgumentName, ExceptionMessages.ListInsertIndexOutOfRange);
        }

        /// <summary>
        /// Creates and <see cref="ArgumentOutOfRangeException"/> that can be thrown when the <b>index</b>
        /// argument supplied to a list remove at operation is out of bounds.
        /// </summary>
        /// <param name="indexArgumentValue">The value of the index argument.</param>
        /// <param name="indexArgumentName">The name of the index argument.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentException ListRemoveAtIndexOutOfRange(object indexArgumentValue, string indexArgumentName)
        {
            return IndexOutOfRange(indexArgumentName, indexArgumentValue);
        }

        #endregion

        #region Collection Based Exceptions

        /// <summary>
        /// Creates an <see cref="ArgumentException"/> that can be thrown when the array supplied 
        /// to <see cref="ICollection{T}.CopyTo"/> has insuffficient space.
        /// </summary>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentException CollectionCopyToArrayInsufficientSpace()
        {
            return CollectionCopyToArrayInsufficientSpace(null);
        }

        /// <summary>
        /// Creates an <see cref="ArgumentException"/> that can be thrown when the array supplied 
        /// to <see cref="ICollection{T}.CopyTo"/> has insuffficient space.
        /// </summary>
        /// <param name="argumentName">The name of the array argument passed to the <b>CopyTo</b> method.</param>
        /// <returns>The newly constructed exception.</returns>
        public static ArgumentException CollectionCopyToArrayInsufficientSpace(string argumentName)
        {
            if (string.IsNullOrEmpty(argumentName))
            {
                argumentName = "array";
            }

            return new ArgumentException(ExceptionMessages.CollectionCopyToArrayInsufficientSpace, argumentName);
        }

        /// <summary>
        /// Create an <see cref="ArgumentException"/> that can be thrown when the array supplied
        /// to <see cref="ICollection{T}.CopyTo"/> has a rank (dimensions) other than 1.
        /// </summary>
        /// <param name="arrayArgumentName">Name of the array argument.</param>
        /// <returns>A new exception.</returns>
        public static ArgumentException CollectionCopyToArrayRankInvalid(string arrayArgumentName)
        {
            return new ArgumentException(ExceptionMessages.CollectionCopyToRankInvalid, arrayArgumentName);
        }

        /// <summary>
        /// Returns a <see cref="NotSupportedException"/> that can be used when an attempt 
        /// is made to add or remove an item from a fixed sized list.
        /// </summary>
        /// <returns>A new <see cref="NotSupportedException"/>.</returns>
        public static NotSupportedException CollectionIsReadOnly()
        {
            // TODO: Add message
            return new NotSupportedException();
        }

        /// <summary>
        /// Returns a <see cref="NotSupportedException"/> that can be used when an attempt 
        /// is made to add or remove an item from a fixed sized list.
        /// </summary>
        /// <returns>A new <see cref="NotSupportedException"/>.</returns>
        public static NotSupportedException CollectionIsFixedSize()
        {
            // TODO: Add message
            return new NotSupportedException();
        }

        #endregion

        #region Enumerator Based Exceptions

        /// <summary>
        /// Creates an <see cref="InvalidOperationException"/> that can be thrown when an 
        /// enumerator has been accessed and the underlying collection has been modified.
        /// </summary>
        /// <returns>The newly constructed exception.</returns>
        public static InvalidOperationException EnumeratorModified()
        {
            return new InvalidOperationException(ExceptionMessages.EnumeratorModified);
        }

        /// <summary>
        /// Enumerators the not started.
        /// </summary>
        /// <returns>A new exception.</returns>
        public static InvalidOperationException EnumeratorNotStarted()
        {
            return new InvalidOperationException(ExceptionMessages.EnumeratorNotStarted);
        }

        /// <summary>
        /// Enumerators the finished.
        /// </summary>
        public static InvalidOperationException EnumeratorFinished()
        {
            return new InvalidOperationException(ExceptionMessages.EnumeratorFinished);
        }

        #endregion

        public static ArgumentException DuplicateKey(string argumentName)
        {
            return new ArgumentException("Duplicate key.", argumentName);
        }

        public static InvalidOperationException EnumeratorCurrentRemoved()
        {
            return new InvalidOperationException("The current item has been removed.");
        }

        public static KeyNotFoundException KeyNotFound()
        {
            throw new KeyNotFoundException();
        }
    }
}
